using System.Text.Json;
using RiceShop.Models;
using Microsoft.EntityFrameworkCore;
using System.Net.Http;
using Microsoft.Extensions.Options;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using System.Security.Cryptography;

namespace RiceShop.Services
{
    /// <summary>
    /// 用户服务接口
    /// </summary>
    public interface IUserService
    {
        /// <summary>
        /// 获取用户信息
        /// </summary>
        Task<User> GetUserProfileAsync(long userId);

        /// <summary>
        /// 更新用户信息
        /// </summary>
        Task<User> UpdateUserProfileAsync(long userId, User userUpdate);

        /// <summary>
        /// 绑定手机号
        /// </summary>
        Task<bool> BindPhoneAsync(long userId, string phoneNumber);

        /// <summary>
        /// 微信登录
        /// </summary>
        Task<User> WeChatLoginAsync(string code);

        /// <summary>
        /// 获取用户列表
        /// </summary>
        IEnumerable<User> GetUsers(string search, string sortBy, bool ascending, int page, int pageSize);

        /// <summary>
        /// 获取用户总数
        /// </summary>
        int GetUsersCount(string search);

        /// <summary>
        /// 创建新用户
        /// </summary>
        /// <param name="user">用户信息</param>
        /// <returns>创建的用户信息</returns>
        Task<User> CreateUserAsync(User user);

        /// <summary>
        /// 更新用户信息（管理员用）
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <param name="user">更新后的用户信息</param>
        /// <returns>操作结果</returns>
        Task<User> UpdateUserAsync(long id, User user);

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <returns>操作结果</returns>
        Task<bool> DeleteUserAsync(long id);

        /// <summary>
        /// 获取用户详细信息
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <returns>用户信息</returns>
        Task<User> GetUserByIdAsync(long id);

        /// <summary>
        /// 微信登录
        /// </summary>
        Task<ApiResponse<TokenResult>> WxLogin(WxLoginModel model);

        /// <summary>
        /// 微信手机号一键登录
        /// </summary>
        Task<ApiResponse<TokenResult>> WxPhoneLogin(WxPhoneLoginModel model);
    }

    /// <summary>
    /// 用户服务实现类
    /// 提供用户信息管理、微信登录等功能
    /// </summary>
    public class UserService : IUserService
    {
        private readonly ApplicationDbContext _context;
        private readonly IConfiguration _configuration;
        private readonly HttpClient _httpClient;
        private readonly WxConfig _wxConfig;
        private readonly IHttpClientFactory _httpClientFactory;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="context">数据库上下文</param>
        /// <param name="configuration">配置信息</param>
        /// <param name="httpClientFactory">HTTP客户端工厂</param>
        /// <param name="wxConfig">微信配置</param>
        public UserService(
            ApplicationDbContext context,
            IConfiguration configuration,
            IHttpClientFactory httpClientFactory,
            IOptions<WxConfig> wxConfig)
        {
            _context = context;
            _configuration = configuration;
            _httpClient = httpClientFactory.CreateClient();
            _wxConfig = wxConfig.Value;
            _httpClientFactory = httpClientFactory;
        }

        /// <summary>
        /// 获取用户信息
        /// 排除已删除的用户
        /// </summary>
        public async Task<User> GetUserProfileAsync(long userId)
        {
            var user = await _context.Users
                .FirstOrDefaultAsync(u => u.Id == userId && !u.IsDeleted);

            if (user == null)
            {
                throw new KeyNotFoundException("用户不存在");
            }

            return user;
        }

        /// <summary>
        /// 更新用户基本信息
        /// 包括昵称、性别、头像等
        /// </summary>
        public async Task<User> UpdateUserProfileAsync(long userId, User userUpdate)
        {
            var user = await _context.Users
                .FirstOrDefaultAsync(u => u.Id == userId && !u.IsDeleted);

            if (user == null)
            {
                throw new KeyNotFoundException("用户不存在");
            }

            user.NickName = userUpdate.NickName;

            user.Gender = userUpdate.Gender;
            user.AvatarUrl = userUpdate.AvatarUrl;
            user.UpdateTime = DateTime.UtcNow;

            await _context.SaveChangesAsync();
            return user;
        }

        /// <summary>
        /// 绑定用户手机号
        /// </summary>
        public async Task<bool> BindPhoneAsync(long userId, string phoneNumber)
        {
            var user = await _context.Users
                .FirstOrDefaultAsync(u => u.Id == userId && !u.IsDeleted);

            if (user == null)
            {
                throw new KeyNotFoundException("用户不存在");
            }

            user.PhoneNumber = phoneNumber;
            user.UpdateTime = DateTime.UtcNow;

            await _context.SaveChangesAsync();
            return true;
        }

        /// <summary>
        /// 微信登录
        /// 通过code获取用户信息，不存在则创建新用户
        /// </summary>
        public async Task<User> WeChatLoginAsync(string code)
        {
            var appId = _configuration["WeChat:AppId"] ?? throw new InvalidOperationException("WeChat AppId not configured");
            var appSecret = _configuration["WeChat:AppSecret"] ?? throw new InvalidOperationException("WeChat AppSecret not configured");

            // 获取access_token
            var tokenUrl = $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={appId}&secret={appSecret}&code={code}&grant_type=authorization_code";
            var tokenResponse = await _httpClient.GetAsync(tokenUrl);
            tokenResponse.EnsureSuccessStatusCode();

            var tokenContent = await tokenResponse.Content.ReadAsStringAsync();
            var tokenInfo = JsonSerializer.Deserialize<WeChatAccessToken>(tokenContent)
                ?? throw new InvalidOperationException("Failed to deserialize access token response");

            // 获取用户信息
            var userInfoUrl = $"https://api.weixin.qq.com/sns/userinfo?access_token={tokenInfo.access_token}&openid={tokenInfo.openid}&lang=zh_CN";
            var userInfoResponse = await _httpClient.GetAsync(userInfoUrl);
            userInfoResponse.EnsureSuccessStatusCode();

            var userInfoContent = await userInfoResponse.Content.ReadAsStringAsync();
            using var document = JsonDocument.Parse(userInfoContent);
            var wechatUserInfo = document.RootElement;

            // 获取或创建用户
            var user = await _context.Users
                .FirstOrDefaultAsync(u => u.OpenId == tokenInfo.openid);

            if (user == null)
            {
                user = new User
                {
                    OpenId = tokenInfo.openid,
                    NickName = wechatUserInfo.GetProperty("nickname").GetString() ?? string.Empty,
                    AvatarUrl = wechatUserInfo.GetProperty("headimgurl").GetString() ?? string.Empty,
                    Gender = (byte)(wechatUserInfo.GetProperty("sex").GetInt32()),
                    CreateTime = DateTime.UtcNow,
                    UpdateTime = DateTime.UtcNow
                };
                _context.Users.Add(user);
            }
            else
            {
                user.NickName = wechatUserInfo.GetProperty("nickname").GetString() ?? string.Empty;
                user.AvatarUrl = wechatUserInfo.GetProperty("headimgurl").GetString() ?? string.Empty;
                user.Gender = (byte)(wechatUserInfo.GetProperty("sex").GetInt32());
                user.UpdateTime = DateTime.UtcNow;
            }

            await _context.SaveChangesAsync();
            return user;
        }

        /// <summary>
        /// 获取用户列表
        /// </summary>
        public IEnumerable<User> GetUsers(string search, string sortBy, bool ascending, int page, int pageSize)
        {
            var query = _context.Users
                .Where(u => !u.IsDeleted &&
                    (string.IsNullOrEmpty(search) ||
                    u.NickName.Contains(search) ||
                    u.PhoneNumber.Contains(search)));

            // 根据sortBy参数进行排序
            query = sortBy.ToLower() switch
            {
                "nickname" => ascending ? query.OrderBy(u => u.NickName) : query.OrderByDescending(u => u.NickName),
                "createtime" => ascending ? query.OrderBy(u => u.CreateTime) : query.OrderByDescending(u => u.CreateTime),
                "updatetime" => ascending ? query.OrderBy(u => u.UpdateTime) : query.OrderByDescending(u => u.UpdateTime),
                _ => ascending ? query.OrderBy(u => u.Id) : query.OrderByDescending(u => u.Id)
            };

            return query
                .Skip((page - 1) * pageSize)
                .Take(pageSize)
                .ToList();
        }

        /// <summary>
        /// 获取用户总数
        /// </summary>
        public int GetUsersCount(string search)
        {
            return _context.Users
                .Count(u => !u.IsDeleted &&
                    (string.IsNullOrEmpty(search) ||
                    u.NickName.Contains(search) ||
                    u.PhoneNumber.Contains(search)));
        }

        /// <summary>
        /// 创建新用户
        /// </summary>
        /// <param name="user">用户信息</param>
        /// <returns>创建的用户信息</returns>
        public async Task<User> CreateUserAsync(User user)
        {
            _context.Users.Add(user);
            await _context.SaveChangesAsync();
            return user;
        }

        /// <summary>
        /// 更新用户信息（管理员用）
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <param name="user">更新后的用户信息</param>
        /// <returns>操作结果</returns>
        public async Task<User> UpdateUserAsync(long id, User user)
        {
            var existingUser = await _context.Users
                .FirstOrDefaultAsync(u => u.Id == id && !u.IsDeleted);

            if (existingUser == null)
            {
                throw new KeyNotFoundException("用户不存在");
            }

            existingUser.NickName = user.NickName;
            existingUser.PhoneNumber = user.PhoneNumber;
            // existingUser.Email = user.Email;
            // existingUser.Address = user.Address;
            // existingUser.Birthday = user.Birthday;
            existingUser.Gender = user.Gender;
            existingUser.AvatarUrl = user.AvatarUrl;
            existingUser.UpdateTime = DateTime.UtcNow;

            await _context.SaveChangesAsync();
            return existingUser;
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <returns>操作结果</returns>
        public async Task<bool> DeleteUserAsync(long id)
        {
            var user = await _context.Users
                .FirstOrDefaultAsync(u => u.Id == id && !u.IsDeleted);

            if (user == null)
            {
                throw new KeyNotFoundException("用户不存在");
            }

            user.IsDeleted = true;
            user.UpdateTime = DateTime.UtcNow;

            await _context.SaveChangesAsync();
            return true;
        }

        /// <summary>
        /// 获取用户详细信息
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <returns>用户信息</returns>
        public async Task<User> GetUserByIdAsync(long id)
        {
            var user = await _context.Users
                .FirstOrDefaultAsync(u => u.Id == id && !u.IsDeleted);

            if (user == null)
            {
                throw new KeyNotFoundException("用户不存在");
            }

            return user;
        }

        /// <summary>
        /// 微信登录
        /// </summary>
        public async Task<ApiResponse<TokenResult>> WxLogin(WxLoginModel model)
        {
            try
            {
                // 1. 通过code获取微信openid和session_key
                var wxLoginResult = await GetWxOpenId(model.Code);
                if (wxLoginResult == null)
                {
                    return ApiResponse<TokenResult>.Error("微信登录失败");
                }

                // 2. 查找或创建用户
                var user = await _context.Users
                    .FirstOrDefaultAsync(u => u.OpenId == wxLoginResult.openid);

                if (user == null)
                {
                    // 首次登录，创建新用户
                    user = new User
                    {
                        OpenId = wxLoginResult.openid,
                        NickName = model.UserInfo.NickName,
                        AvatarUrl = model.UserInfo.AvatarUrl,
                        Gender = byte.Parse(model.UserInfo.Gender),
                        Country = model.UserInfo.Country,
                        Province = model.UserInfo.Province,
                        City = model.UserInfo.City,
                        CreateTime = DateTime.Now,
                        UpdateTime = DateTime.Now,
                        LastLoginTime = DateTime.Now,
                        Status = 1 // 正常状态
                    };

                    _context.Users.Add(user);
                    await _context.SaveChangesAsync();
                }
                else
                {
                    // 更新用户信息
                    user.NickName = model.UserInfo.NickName;
                    user.AvatarUrl = model.UserInfo.AvatarUrl;
                    user.Gender = byte.Parse(model.UserInfo.Gender);
                    user.UpdateTime = DateTime.Now;
                    user.LastLoginTime = DateTime.Now;
                    await _context.SaveChangesAsync();
                }

                // 3. 生成JWT令牌
                var tokenResult = GenerateUserToken(user);

                return ApiResponse<TokenResult>.Ok(tokenResult, "登录成功");
            }
            catch (Exception ex)
            {
                // 记录日志
                return ApiResponse<TokenResult>.Error($"登录失败: {ex.Message}");
            }
        }

        private async Task<WxLoginResult?> GetWxOpenId(string code)
        {
            try
            {
                var client = _httpClientFactory.CreateClient();
                var url = $"https://api.weixin.qq.com/sns/jscode2session?appid={_wxConfig.AppId}&secret={_wxConfig.AppSecret}&js_code={code}&grant_type=authorization_code";
                
                Console.WriteLine($"调用微信接口获取session_key: {url}");
                
                var response = await client.GetAsync(url);
                if (response.IsSuccessStatusCode)
                {
                    var content = await response.Content.ReadAsStringAsync();
                    Console.WriteLine($"微信接口响应: {content}");
                    
                    var result = JsonSerializer.Deserialize<WxLoginResult>(content);
                    
                    // 检查微信接口是否返回错误
                    if (result != null && result.errcode != 0)
                    {
                        Console.WriteLine($"微信接口返回错误: errcode={result.errcode}, errmsg={result.errmsg}");
                        return null;
                    }
                    
                    if (result != null && !string.IsNullOrEmpty(result.openid) && !string.IsNullOrEmpty(result.session_key))
                    {
                        Console.WriteLine($"成功获取OpenId: {result.openid}, SessionKey长度: {result.session_key.Length}");
                        return result;
                    }
                    else
                    {
                        Console.WriteLine("微信接口返回数据不完整");
                        return null;
                    }
                }
                else
                {
                    Console.WriteLine($"微信接口调用失败: {response.StatusCode}");
                    return null;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"调用微信接口异常: {ex.Message}");
                return null;
            }
        }

        private TokenResult GenerateUserToken(User user)
        {
            var jwtKey = _configuration["Jwt:Key"] ?? 
                throw new InvalidOperationException("JWT Key is not configured");
            var issuer = _configuration["Jwt:Issuer"] ?? 
                throw new InvalidOperationException("JWT Issuer is not configured");
            var audience = _configuration["Jwt:Audience"] ?? 
                throw new InvalidOperationException("JWT Audience is not configured");

            var claims = new[]
            {
                new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.NickName),
                new Claim("OpenId", user.OpenId)
            };

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
                issuer: issuer,
                audience: audience,
                claims: claims,
                expires: DateTime.Now.AddDays(1),
                signingCredentials: creds);

            return new TokenResult
            {
                AccessToken = new JwtSecurityTokenHandler().WriteToken(token),
                ExpiresIn = 86400, // 24小时
                ExpiresAt = DateTime.Now.AddDays(1)
            };
        }

        public async Task<ApiResponse<TokenResult>> WxPhoneLogin(WxPhoneLoginModel model)
        {
            try
            {
                // 1. 通过code获取微信openid和session_key
                var wxLoginResult = await GetWxOpenId(model.Code);
                if (wxLoginResult == null)
                {
                    return ApiResponse<TokenResult>.Error("微信登录失败：无法获取OpenID");
                }

                // 2. 解密手机号数据
                try
                {
                    var phoneInfo = DecryptPhoneNumber(model.EncryptedData, model.Iv, wxLoginResult.session_key);
                    if (phoneInfo == null)
                    {
                        return ApiResponse<TokenResult>.Error("获取手机号失败：解密失败");
                    }

                    // 3. 查找或创建用户
                    var user = await _context.Users
                        .FirstOrDefaultAsync(u => u.OpenId == wxLoginResult.openid);

                    if (user == null)
                    {
                        // 首次登录，创建新用户，确保所有必要字段都有值
                        user = new User
                        {
                            OpenId = wxLoginResult.openid,
                            PhoneNumber = phoneInfo.phoneNumber,
                            NickName = "微信用户", // 设置默认昵称
                            AvatarUrl = "", // 设置默认头像
                            Gender = 0, // 设置默认性别
                            Country = "",
                            Province = "",
                            City = "",
                            CreateTime = DateTime.Now,
                            UpdateTime = DateTime.Now,
                            LastLoginTime = DateTime.Now,
                            Status = 1, // 正常状态
                            IsDeleted = false
                        };

                        _context.Users.Add(user);
                        await _context.SaveChangesAsync();
                    }
                    else
                    {
                        // 更新用户信息
                        user.PhoneNumber = phoneInfo.phoneNumber;
                        user.UpdateTime = DateTime.Now;
                        user.LastLoginTime = DateTime.Now;
                        
                        _context.Users.Update(user);
                        await _context.SaveChangesAsync();
                    }

                    // 4. 生成JWT令牌
                    var tokenResult = GenerateUserToken(user);

                    return ApiResponse<TokenResult>.Ok(tokenResult, "登录成功");
                }
                catch (Exception ex)
                {
                    // 记录详细的错误信息
                    Console.WriteLine($"解密手机号或保存用户时出错: {ex.Message}");
                    Console.WriteLine($"Stack Trace: {ex.StackTrace}");
                    if (ex.InnerException != null)
                    {
                        Console.WriteLine($"Inner Exception: {ex.InnerException.Message}");
                    }
                    return ApiResponse<TokenResult>.Error($"解密手机号失败：{ex.Message}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"微信手机号登录失败: {ex.Message}");
                return ApiResponse<TokenResult>.Error($"登录失败: {ex.Message}");
            }
        }

        private WxPhoneResult? DecryptPhoneNumber(string encryptedData, string iv, string sessionKey)
        {
            try
            {
                Console.WriteLine($"开始解密手机号数据...");
                Console.WriteLine($"EncryptedData Length: {encryptedData?.Length ?? 0}");
                Console.WriteLine($"IV Length: {iv?.Length ?? 0}");
                Console.WriteLine($"SessionKey Length: {sessionKey?.Length ?? 0}");
                Console.WriteLine($"AppId: {_wxConfig.AppId}");
                
                // 检查必要参数是否为null
                if (string.IsNullOrEmpty(sessionKey))
                {
                    Console.WriteLine("SessionKey 为空或null");
                    return null;
                }
                
                if (string.IsNullOrEmpty(encryptedData))
                {
                    Console.WriteLine("EncryptedData 为空或null");
                    return null;
                }
                
                if (string.IsNullOrEmpty(iv))
                {
                    Console.WriteLine("IV 为空或null");
                    return null;
                }
                
                var decryptor = new WeChatDataCrypt(_wxConfig.AppId, sessionKey);
                var decryptedData = decryptor.Decrypt(encryptedData, iv);
                
                Console.WriteLine($"解密成功，解密后数据: {decryptedData}");
                
                var phoneResult = JsonSerializer.Deserialize<WxPhoneResult>(decryptedData);
                
                // 验证数据完整性 - 检查 watermark 中的 appid 是否匹配
                if (phoneResult?.watermark?.appid != _wxConfig.AppId)
                {
                    Console.WriteLine($"AppId 验证失败: 期望 {_wxConfig.AppId}, 实际 {phoneResult?.watermark?.appid}");
                    return null;
                }
                
                Console.WriteLine($"手机号解密成功: {phoneResult.phoneNumber}");
                return phoneResult;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"解密手机号数据失败: {ex.Message}");
                Console.WriteLine($"Stack Trace: {ex.StackTrace}");
                return null;
            }
        }

        // 添加微信数据解密类
        public class WeChatDataCrypt
        {
            private readonly string _appId;
            private readonly string _sessionKey;

            public WeChatDataCrypt(string appId, string sessionKey)
            {
                _appId = appId;
                _sessionKey = sessionKey;
            }

            public string Decrypt(string encryptedData, string iv)
            {
                try
                {
                    Console.WriteLine("开始AES解密...");
                    
                    // 验证输入参数
                    if (string.IsNullOrEmpty(encryptedData))
                        throw new ArgumentException("加密数据不能为空");
                    if (string.IsNullOrEmpty(iv))
                        throw new ArgumentException("初始化向量不能为空");
                    if (string.IsNullOrEmpty(_sessionKey))
                        throw new ArgumentException("会话密钥不能为空");
                        
                    var keyBytes = Convert.FromBase64String(_sessionKey);
                    var ivBytes = Convert.FromBase64String(iv);
                    var encryptedBytes = Convert.FromBase64String(encryptedData);

                    Console.WriteLine($"密钥长度: {keyBytes.Length}, IV长度: {ivBytes.Length}, 加密数据长度: {encryptedBytes.Length}");

                    using var aes = Aes.Create();
                    aes.Key = keyBytes;
                    aes.IV = ivBytes;
                    aes.Mode = CipherMode.CBC;
                    aes.Padding = PaddingMode.PKCS7;

                    using var decryptor = aes.CreateDecryptor();
                    using var msDecrypt = new MemoryStream(encryptedBytes);
                    using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
                    using var srDecrypt = new StreamReader(csDecrypt, Encoding.UTF8);
                    
                    var decryptedData = srDecrypt.ReadToEnd();
                    Console.WriteLine($"AES解密完成，数据长度: {decryptedData.Length}");
                    return decryptedData;
                }
                catch (FormatException ex)
                {
                    throw new Exception($"Base64解码失败: {ex.Message}");
                }
                catch (CryptographicException ex)
                {
                    throw new Exception($"AES解密失败: {ex.Message}");
                }
                catch (Exception ex)
                {
                    throw new Exception($"解密过程出错: {ex.Message}");
                }
            }
        }
    }

    public class WxLoginResult
    {
        public string openid { get; set; } = string.Empty;
        public string session_key { get; set; } = string.Empty;
        public string? unionid { get; set; }  // 可能为空
        public int errcode { get; set; }
        public string errmsg { get; set; } = string.Empty;
    }

    public class AccessTokenResult
    {
        public string? access_token { get; set; }
        public int expires_in { get; set; }
        public int errcode { get; set; }
        public string? errmsg { get; set; }
    }

    public class WxPhoneResponse
    {
        public int errcode { get; set; }
        public string? errmsg { get; set; }
        public PhoneInfo? phone_info { get; set; }
    }

    public class PhoneInfo
    {
        public string phoneNumber { get; set; } = string.Empty;
        public string purePhoneNumber { get; set; } = string.Empty;
        public string countryCode { get; set; } = string.Empty;
        public WatermarkInfo watermark { get; set; } = null!;
    }

    public class WatermarkInfo
    {
        public string appid { get; set; } = string.Empty;
        public long timestamp { get; set; }
    }
}